﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using AspNetCore.Web.Config;
using StackExchange.Redis;

namespace AspNetCore.Web.Caching
{
    public class RedisConnectionWrapper : IRedisConnectionWrapper
    {

        private readonly object _lock = new object();
        private readonly CacheConfig _config;
        private readonly Lazy<string> _connectionString;
        private volatile ConnectionMultiplexer _connection;

        public RedisConnectionWrapper(CacheConfig cacheConfig)
        {
            _config = cacheConfig;
            this._connectionString = new Lazy<string>(GetConnectionString);
        }

        /// <summary>
        /// 从配置中获取连接
        /// </summary>
        /// <returns></returns>
        protected string GetConnectionString()
        {
            return _config.RedisCachingConnectionString;
        }

        /// <summary>
        /// 获取到Redis服务器的连接
        /// </summary>
        /// <returns></returns>
        protected ConnectionMultiplexer GetConnection()
        {
            if (_connection != null && _connection.IsConnected) return _connection;

            lock (_lock)
            {
                if (_connection != null && _connection.IsConnected) return _connection;

                _connection?.Dispose();

                _connection = ConnectionMultiplexer.Connect(_connectionString.Value);
            }

            return _connection;
        }

        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        { 
            _connection?.Dispose();
        }

        /// <summary>
        /// 删除数据库的所有键
        /// </summary>
        /// <param name="db"></param>
        public void FlushDatabase(int? db = null)
        {
            var endPoints = GetEndPoints();

            foreach (var endPoint in endPoints)
            {
                GetServer(endPoint).FlushDatabase(db ?? -1);
            }
        }

        /// <summary>
        /// 获取到Redis内部数据库的交互式连接
        /// </summary>
        /// <param name="db">数据库数量;传递null以使用默认值。</param>
        /// <returns></returns>
        public IDatabase GetDatabase(int? db = null)
        {
            return GetConnection().GetDatabase(db ?? -1);
        }

        /// <summary>
        /// 获取服务器上定义的所有端点
        /// </summary>
        /// <returns></returns>
        public EndPoint[] GetEndPoints()
        {
            return GetConnection().GetEndPoints();
        }

        /// <summary>
        /// 获取单个服务器的配置API
        /// </summary>
        /// <param name="endPoint"></param>
        /// <returns></returns>
        public IServer GetServer(EndPoint endPoint)
        {
            return GetConnection().GetServer(endPoint);
        }
    }
}
